#pragma once

#include "comm/znx_string.h"


#define ZNX_HTTP_MIN_WRITEABLE_SIZE                 128
#define ZNX_HTTP_MAX_WRITE_IOV                      4


// http scheme
#define ZNX_SCHEME_HTTP                             "http"
#define ZNX_SCHEME_HTTP_LEN                         (sizeof("http") - 1)
#define ZNX_SCHEME_HTTPS                            "https"
#define ZNX_SCHEME_HTTPS_LEN                        (sizeof("https") - 1)


// http version
#define ZNX_HTTP_VERSION_9                          9
#define ZNX_HTTP_VERSION_10                         1000
#define ZNX_HTTP_VERSION_11                         1001
#define ZNX_HTTP_VERSION_20                         2000
#define ZNX_HTTP_VERSION_QUIC                       3000

#define ZNX_HTTP_VERSION_PREFIX                     "HTTP/"
#define ZNX_HTTP_VERSION_PREFIX_LEN                 (sizeof("HTTP/") - 1)
#define ZNX_HTTP_VERSION_10_STR                     "HTTP/1.0"
#define ZNX_HTTP_VERSION_10_STR_LEN                 (sizeof("HTTP/1.0") - 1)
#define ZNX_HTTP_VERSION_11_STR                     "HTTP/1.1"
#define ZNX_HTTP_VERSION_11_STR_LEN                 (sizeof("HTTP/1.1") - 1)


// http response status
#define ZNX_HTTP_CONTINUE                           100
#define ZNX_HTTP_SWITCHING_PROTOCOLS                101
#define ZNX_HTTP_PROCESSING                         102
#define ZNX_HTTP_OK                                 200
#define ZNX_HTTP_CREATED                            201
#define ZNX_HTTP_ACCEPTED                           202
#define ZNX_HTTP_NO_CONTENT                         204
#define ZNX_HTTP_PARTIAL_CONTENT                    206
#define ZNX_HTTP_MULTIPLE_CHOICES                   300
#define ZNX_HTTP_MOVED_PERMANENTLY                  301
#define ZNX_HTTP_MOVED_TEMPORARILY                  302
#define ZNX_HTTP_NOT_MODIFIED                       304
#define ZNX_HTTP_TEMPORARY_REDIRECT                 307
#define ZNX_HTTP_PERMANENT_REDIRECT                 308
#define ZNX_HTTP_BAD_REQUEST                        400
#define ZNX_HTTP_UNAUTHORIZED                       401
#define ZNX_HTTP_FORBIDDEN                          403
#define ZNX_HTTP_NOT_FOUND                          404
#define ZNX_HTTP_NOT_ALLOWED                        405
#define ZNX_HTTP_REQUEST_TIME_OUT                   408
#define ZNX_HTTP_LENGTH_REQUIRED                    411
#define ZNX_HTTP_REQUEST_ENTITY_TOO_LARGE           413
#define ZNX_HTTP_REQUEST_URI_TOO_LARGE              414
#define ZNX_HTTP_RANGE_NOT_SATISFIABLE              416
#define ZNX_HTTP_TOO_MANY_REQUESTS                  429
#define ZNX_HTTP_INTERNAL_SERVER_ERROR              500
#define ZNX_HTTP_NOT_IMPLEMENTED                    501
#define ZNX_HTTP_BAD_GATEWAY                        502
#define ZNX_HTTP_SERVICE_UNAVAILABLE                503
#define ZNX_HTTP_GATEWAY_TIME_OUT                   504
#define ZNX_HTTP_VERSION_NOT_SUPPORTED              505
#define ZNX_HTTP_STATUS_CODE_END                    999


// http header
#define ZNX_HTTP_HOST_HDR                           "Host"
#define ZNX_HTTP_HOST_HDR_LEN                       (sizeof("Host") - 1)
#define ZNX_HTTP_CONNECTION_HDR                     "Connection"
#define ZNX_HTTP_CONNECTION_HDR_LEN                 (sizeof("Connection") - 1)
#define ZNX_HTTP_CONTENT_LENGTH_HDR                 "Content-Length"
#define ZNX_HTTP_CONTENT_LENGTH_HDR_LEN             (sizeof("Content-Length") - 1)
#define ZNX_HTTP_RANGE_HDR                          "Range"
#define ZNX_HTTP_RANGE_HDR_LEN                      (sizeof("Range") - 1)
#define ZNX_HTTP_TRANSFER_ENCODING_HDR              "Transfer-Encoding"
#define ZNX_HTTP_TRANSFER_ENCODING_HDR_LEN          (sizeof("Transfer-Encoding") - 1)
#define ZNX_HTTP_TRAILER_HDR                        "Trailer"
#define ZNX_HTTP_TRAILER_HDR_LEN                    (sizeof("Trailer") - 1)


// http header value
#define ZNX_HTTP_CLOSE                              "close"
#define ZNX_HTTP_CLOSE_LEN                          (sizeof("close") - 1)
#define ZNX_HTTP_CHUNKED                            "chunked"
#define ZNX_HTTP_CHUNKED_LEN                        (sizeof("chunked") - 1)
#define ZNX_HTTP_IDENTITY                           "identity"
#define ZNX_HTTP_IDENTITY_LEN                       (sizeof("identity") - 1)
#define ZNX_HTTP_KEEPALIVE                          "keep-alive"
#define ZNX_HTTP_KEEPALIVE_LEN                      (sizeof("keep-alive") - 1)


// http method
#define ZNX_HTTP_METHOD_GET                         "GET"
#define ZNX_HTTP_METHOD_GET_LEN                     (sizeof("GET") - 1)
#define ZNX_HTTP_METHOD_POST                        "POST"
#define ZNX_HTTP_METHOD_POST_LEN                    (sizeof("POST") - 1)
#define ZNX_HTTP_METHOD_HEAD                        "HEAD"
#define ZNX_HTTP_METHOD_HEAD_LEN                    (sizeof("HEAD") - 1)
#define ZNX_HTTP_METHOD_OPTIONS                     "OPTIONS"
#define ZNX_HTTP_METHOD_OPTIONS_LEN                 (sizeof("OPTIONS") - 1)
#define ZNX_HTTP_METHOD_PUT                         "PUT"
#define ZNX_HTTP_METHOD_PUT_LEN                     (sizeof("PUT") - 1)
#define ZNX_HTTP_METHOD_PATCH                       "PATCH"
#define ZNX_HTTP_METHOD_PATCH_LEN                   (sizeof("PATCH") - 1)
#define ZNX_HTTP_METHOD_DELETE                      "DELETE"
#define ZNX_HTTP_METHOD_DELETE_LEN                  (sizeof("DELETE") - 1)
#define ZNX_HTTP_METHOD_TRACE                       "TRACE"
#define ZNX_HTTP_METHOD_TRACE_LEN                   (sizeof("TRACE") - 1)
#define ZNX_HTTP_METHOD_CONNECT                     "CONNECT"
#define ZNX_HTTP_METHOD_CONNECT_LEN                 (sizeof("CONNECT") - 1)


typedef struct znx_http_request_s           znx_http_request_t;
typedef struct znx_http_response_s          znx_http_response_t;

const char *znx_http_get_response_reason(int status_code);

extern znx_str_t znx_http_host_hdr_name;
extern znx_str_t znx_http_connection_hdr_name;
extern znx_str_t znx_http_content_length_hdr_name;
extern znx_str_t znx_http_range_hdr_name;
extern znx_str_t znx_http_transfer_encoding_hdr_name;
extern znx_str_t znx_http_trailer_hdr_name;


extern znx_str_t znx_http_version_10;
extern znx_str_t znx_http_version_11;



static inline znx_bool_t
znx_http_method_is_head(znx_str_t *method)
{
    if (method->len == 4 &&
        znx_strncmp(method->data, "HEAD", 4) == 0)
    {
        return ZNX_TRUE;
    }

    return ZNX_FALSE;
}


static inline znx_bool_t
znx_http_method_is_get(znx_str_t *method)
{
    if (method->len == 3 &&
        znx_strncmp(method->data, "GET", 3) == 0)
    {
        return ZNX_TRUE;
    }

    return ZNX_FALSE;
}


static inline znx_bool_t
znx_http_method_is_post(znx_str_t *method)
{
    if (method->len == 4 &&
        znx_strncmp(method->data, "POST", 4) == 0)
    {
        return ZNX_TRUE;
    }

    return ZNX_FALSE;
}